<?php

use app\config\Db;
use Core\Utils\Utils;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Formatter;
use Core\Common\Common;
use Core\Result\Result;
require_once "Pay.php";
/**
 * 微信支付回调 TODO
 * @return void
 */
function wechatPayCallback()
{

    $inBodyResourceArray = decrypt();
//        print_r($inBodyResourceArray);die;// 打印解密后的结果
    if ($inBodyResourceArray['trade_state'] !== 'SUCCESS') {
        $content = "订单支付失败=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".($inBodyResourceArray["amount"]["payer_total"] /100).",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("未支付成功");
    }
    $db = new Db("host");
    $orderInfo = $db->find("select order_id,order_no,pay_no,user_id,is_parent,shop_id,pay_status,order_state,coupon_id,sku_id,order_total_price,order_number,order_type,payment_type,order_coupon_price,shipping_fee from `ysmz_shop_goods_order` where `pay_no`='$inBodyResourceArray[out_trade_no]'");
    if(empty($orderInfo) || $orderInfo["pay_status"] != 1 || $orderInfo["order_state"] != 0){
        $content = "订单不存在=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".($inBodyResourceArray["amount"]["payer_total"] /100).",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("订单信息错误");
    }
    $orderInfo["order_pay_price"] = $inBodyResourceArray["amount"]["payer_total"] /100;
    if($orderInfo["shipping_fee"] > 0){
        $orderInfo["order_total_price"] += $orderInfo["shipping_fee"];
    }
    $orderInfo["order_cloud_price"] =0;
    $db->startTrans();
    try {
        if(!empty($orderInfo["coupon_id"])){
            couponSettlement($db,$orderInfo);
        }
        if(in_array($orderInfo["payment_type"],[3,6,7])){//组合支付处理 3云豆组合 6生日组合 7帮扶组合
            $combinedPayment = combinedPayment($db,$orderInfo);
            $orderInfo["order_pay_price"] +=$combinedPayment;
        }
        if($orderInfo["payment_type"] == 2){
            $addDetailSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,ext_desc) values ($orderInfo[user_id],$orderInfo[order_pay_price],2,'$orderInfo[order_no]','商品购买',2,'微信购买')";
            if (!$db->save($addDetailSql)) Common::exception("用户明细记录写入失败");
        }
        orderSettlement($db,$orderInfo);
        $db->commit();
    } catch (\Exception $e) {
        $db->rollback();
        $content = "失败=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".($inBodyResourceArray["amount"]["payer_total"] /100)."原因：".$e->getMessage().",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error($e->getMessage());
    }
    $messagesData["type"] = 2;
    $messagesData["sid"] = $orderInfo["shop_id"];
    $messagesData["msg_type"] = 2;
    $messagesData["msg"] = "用户下单";
    $messagesData["trade_no"] = $orderInfo["order_no"];
    pushCrmMessages($messagesData);
    Result::success();
}

function combinedPayment($db,$data)
{
    $payment_type = $data["payment_type"];
    $user_id = $data['user_id'];
    $order_pay_price = $data['order_pay_price'];//微信支付金额
    $order_total_price = $data['order_total_price'];//订单总金额
    $remainingMoney = $order_total_price - $order_pay_price;
    $ext_desc = "组合支付";
    $userInfo = $db->find("select `user_id`,`cloud_bean`,`birth_bean`,`assist_bean` from `user_info` where `user_id`=$user_id FOR UPDATE");
    switch ($payment_type) {
        case 3 :
            $cloud_bean = $userInfo["cloud_bean"];
            $upSetJoin = "`cloud_bean`=`cloud_bean` - $remainingMoney";
            $upWhereJoin = "`cloud_bean` = $cloud_bean";
            $czSetJpin = "`cloud_bean`=`cloud_bean` + $order_pay_price";
            $czWhereJpin = "`cloud_bean` = $cloud_bean";
            $data_src = 1;
            $ext_desc = "云豆组合";
            break;
        case 6 :
            $cloud_bean = $userInfo["birth_bean"];
            $upSetJoin = "`birth_bean`=`birth_bean` - $remainingMoney";
            $upWhereJoin = "`birth_bean` = $cloud_bean";
            $czSetJpin = "`birth_bean`=`birth_bean` + $order_pay_price";
            $czWhereJpin = "`birth_bean` = $cloud_bean";
            $data_src = 3;
            $ext_desc = "生日组合";
            break;
        case 7 :
            $cloud_bean = $userInfo["assist_bean"];
            $upSetJoin = "`assist_bean`=`assist_bean` - $remainingMoney";
            $upWhereJoin = "`assist_bean` = $cloud_bean";
            $czSetJpin = "`assist_bean`=`assist_bean` + $order_pay_price";
            $czWhereJpin = "`assist_bean` = $cloud_bean";
            $data_src = 4;
            $ext_desc = "帮扶组合";
            break;
    }
    //$cloud_bean = $userInfo["cloud_bean"];
    //$remainingMoney = $order_total_price - $order_pay_price;
    if($remainingMoney > $cloud_bean){
        //完犊子了 钱不够扣 够不扣 结束当前订单，微信支付金额作为用户充值处理
        $content = "完犊子了,钱不够扣=>支付单号：".$data["order_no"].",支付金额：".$order_pay_price.",订单金额：".$order_total_price.",用户余额：".$cloud_bean.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        $paid_time = date("Y-m-d H:i:s",time());
        $rechargeSql = "INSERT INTO `user_recharge_order` ( `user_id`,`pay_no`,`amount`,`status`,`paid_time`) VALUES ($user_id,'$data[pay_no]',$order_pay_price,1,'$paid_time')";
        $upUserSql = "update `user_info` set $czSetJpin where `user_id`=$user_id and $czWhereJpin";//可能会更新负数
        $addOrderSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,new_balance) values ($user_id,$order_pay_price,$data_src,'$data[order_no]','充值',1,$cloud_bean+$order_pay_price)";
        if (!$db->save($rechargeSql)) Common::exception("用户充值记录写入失败");
        if (!$db->save($upUserSql)) Common::exception("用户充值余额更新失败");
        if (!$db->save($addOrderSql)) Common::exception("用户充值流水更新失败");
        $addDetailSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,ext_desc) values ($user_id,$order_pay_price,2,'$data[order_no]','充值',2,'$ext_desc')";
        if (!$db->save($addDetailSql)) Common::exception("用户明细记录写入失败2");
        $db->commit();
        Result::success("成功");
    }
    if($remainingMoney > 0){
        $upUserSql = "update `user_info` set $upSetJoin where `user_id`=$user_id and $upWhereJoin";//可能会更新负数
        $addOrderSql2 = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,new_balance) values ($user_id,$remainingMoney,$data_src,'$data[order_no]','商品购买',2,$cloud_bean-$remainingMoney)";
        if (!$db->save($upUserSql)) Common::exception("用户余额更新失败");
        if (!$db->save($addOrderSql2)) Common::exception("用户云豆流水更新失败");
    }
    $addOrderSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,new_balance,ext_desc) values ($user_id,$order_pay_price,2,'$data[order_no]','商品购买',2,0,'$ext_desc')";
    if (!$db->save($addOrderSql)) Common::exception("用户微信流水更新失败");
    return $remainingMoney;
}
function decrypt()
{
    $time = time();
    $datetime = date('Y-m-d H:i:s', $time);
    $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
    $heards = Common::getHttpHeader();
    $inWechatpaySignature = $heards['Wechatpay-Signature'];// 请根据实际情况获取
    $inWechatpayTimestamp = $heards['Wechatpay-Timestamp'];// 请根据实际情况获取
    $inWechatpaySerial = $heards['Wechatpay-Serial'];// 请根据实际情况获取
    $inWechatpayNonce = $heards['Wechatpay-Nonce'];// 请根据实际情况获取
    $inBody = file_get_contents('php://input');// 请根据实际情况获取，例如: file_get_contents('php://input');
    $file_directory3 = $DOCUMENT_ROOT . '/weiChatPayNotify.log';
    file_put_contents($file_directory3, $datetime . '-heards' . json_encode($heards) . PHP_EOL, FILE_APPEND);
    file_put_contents($file_directory3, $datetime . $inBody . PHP_EOL, FILE_APPEND);
    $config = Common::config('Pay');
    $apiv3Key = $config['wechat']['apiv3Key'];// 在商户平台上设置的APIv3密钥
    // 根据通知的平台证书序列号，查询本地平台证书文件，
    $platformPublicKeyInstance = Rsa::from($config['wechat']['platformCertificateFilePath'], Rsa::KEY_TYPE_PUBLIC);
    // 检查通知时间偏移量，允许5分钟之内的偏移
    $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
    $verifiedStatus = Rsa::verify(
    // 构造验签名串
        Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
        $inWechatpaySignature,
        $platformPublicKeyInstance
    );
    if (!$timeOffsetStatus && !$verifiedStatus) {
//        exit("FAIL");//解密失败输出
        file_put_contents($file_directory3, $datetime . '-heards' . json_encode($heards) . PHP_EOL, FILE_APPEND);
        file_put_contents($file_directory3, $datetime . $inBody . PHP_EOL, FILE_APPEND);
        $content = "支付解密失败=>参数：".$inBody.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("解密失败或超时");
    }
    // 转换通知的JSON文本消息为PHP Array数组
    $inBodyArray = (array)json_decode($inBody, true);
    // 使用PHP7的数据解构语法，从Array中解构并赋值变量
    ['resource' => [
        'ciphertext' => $ciphertext,
        'nonce' => $nonce,
        'associated_data' => $aad
    ]] = $inBodyArray;
    // 加密文本消息解密
    $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
    // 把解密后的文本转换为PHP Array数组
    return (array)json_decode($inBodyResource, true);
}

/**
 * 会员充值支付 TODO
 * @return void
 */
function rechargePayCallback()
{
    $time = time();
    $datetime = date('Y-m-d H:i:s', $time);
    $inBodyResourceArray = decrypt();
    $payer_total = ($inBodyResourceArray["amount"]["payer_total"] /100);//用户实际支付
    if ($inBodyResourceArray['trade_state'] !== 'SUCCESS') {
        $content = "充值支付失败=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("未支付成功");
    }
    $db = new Db("host");
    $orderInfo = $db->find("select order_id,user_id,pay_no,amount,status,type from `user_recharge_order` where `pay_no`='$inBodyResourceArray[out_trade_no]'");
    if(empty($orderInfo) || $orderInfo["status"] != 0){
        $content = "充值不存在=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("订单信息错误");
    }
    $order_id = $orderInfo["order_id"];
    $user_id = $orderInfo["user_id"];
    $type = $orderInfo["type"];
    $userInfo = $db->find("select `cloud_bean`,`birth_bean`,`assist_bean`,`openid` from `user_info` where `user_id`=$user_id");
    switch ($type) {
        case 1 :
            $cloud_bean = $userInfo["cloud_bean"];
            $czSetJpin = "`cloud_bean`=`cloud_bean` + $payer_total";
            $czWhereJpin = "`cloud_bean` = $cloud_bean";
            $data_src = 1;
            $ext_desc = "云豆充值";
            break;
        case 2 :
            $cloud_bean = $userInfo["birth_bean"];
            $czSetJpin = "`birth_bean`=`birth_bean` + $payer_total";
            $czWhereJpin = "`birth_bean` = $cloud_bean";
            $data_src = 3;
            $ext_desc = "生日豆充值";
            break;
        case 3 :
            $cloud_bean = $userInfo["assist_bean"];
            $czSetJpin = "`assist_bean`=`assist_bean` + $payer_total";
            $czWhereJpin = "`assist_bean` = $cloud_bean";
            $data_src = 4;
            $ext_desc = "帮扶豆充值";
            break;
        default:
            $content = "充值类型不存在=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
            Utils::writePayLog($content);
            Result::error("订单类型错误");
            break;
    }
    if(empty($userInfo)){
        $content = "充值用户不存在=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("用户信息错误");
    }
    $data_id = $orderInfo["pay_no"];
    $data_remarks = "微信充值";
    $upOrderSql = "update `user_recharge_order` set `amount`=$payer_total,`status`=1,`paid_time` = '$datetime' where `order_id`=$order_id and `user_id` = $user_id";
    $upUserSql = "update `user_info` set $czSetJpin where `user_id`=$user_id and $czWhereJpin";
    $addOrderSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,new_balance,ext_desc) values ($user_id,$payer_total,$data_src,'$data_id','$data_remarks',1,$cloud_bean+$payer_total,'$ext_desc')";
    $addDetailSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,ext_desc) values ($user_id,$payer_total,2,'$data_id','$data_remarks',2,'$ext_desc')";
    $shippingData["out_trade_no"] = $inBodyResourceArray["out_trade_no"];
    $shippingData["item_desc"] = $data_remarks;
    $shippingData["logistics_type"] = 3;
    $shippingData["openid"] = $userInfo["openid"];
    sleep(3);
    $db->startTrans();
    try {
        $uploadShippingInfo = uploadShippingInfo($shippingData);//微信发货通知
        if($uploadShippingInfo["errcode"] != 0){
            $content = "微信发货通知失败=>错误代码：".$uploadShippingInfo["errcode"].",错误原因：".$uploadShippingInfo["errmsg"]."单号：".$inBodyResourceArray["out_trade_no"].",时间：".date("Y-m-d H:i:s",time());
            Utils::writePayLog($content);
        }
        if (!$db->save($upOrderSql)) Common::exception("订单更新失败");
        if (!$db->save($upUserSql)) Common::exception("用户余额更新失败");
        if (!$db->save($addOrderSql)) Common::exception("用户流水更新失败");
        if (!$db->save($addDetailSql)) Common::exception("用户明细记录写入失败3");
        $db->commit();
    } catch (\Exception $e) {
        $db->rollback();
        $content = "充值失败=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",原因：".$e->getMessage().",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error($e->getMessage());
    }
    Result::success();
}
function scanPayCallback()
{
    $time = time();
    $datetime = date('Y-m-d H:i:s', $time);
    $inBodyResourceArray = decrypt();
    $payer_total = ($inBodyResourceArray["amount"]["payer_total"] /100);//用户实际支付
    /*$content = "扫码付支付失败=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
    Utils::writePayLog($content);*/
    if ($inBodyResourceArray['trade_state'] !== 'SUCCESS') {
        $content = "扫码付支付失败=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("未支付成功");
    }
    $db = new Db("host");
    $orderInfo = $db->find("select order_id,user_id,sid,pay_no,amount,status,type from `user_scan_order` where `pay_no`='$inBodyResourceArray[out_trade_no]'");
    if(empty($orderInfo) || $orderInfo["status"] != 0){
        $content = "扫码付不存在=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("订单信息错误");
    }
    $order_id = $orderInfo["order_id"];
    $user_id = $orderInfo["user_id"];
    $userInfo = $db->find("select `cloud_bean`,`openid` from `user_info` where `user_id`=$user_id");
    if(empty($userInfo)){
        $content = "扫码付用户不存在=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error("用户信息错误");
    }
    $queryMerchantName = queryMerchantName($orderInfo["sid"],$orderInfo["type"]);
    $data_src = 2;
    $data_id = $orderInfo["pay_no"];
    $data_remarks = "扫码付-".$queryMerchantName;
    $upOrderSql = "update `user_scan_order` set `amount`=$payer_total,`status`=1,`paid_time` = '$datetime',`payment_type` = 2 where `order_id`= $order_id and `user_id` = $user_id";
    $addOrderSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,ext_desc) values ($user_id,$payer_total,$data_src,'$data_id','$data_remarks',2,'微信扫码')";
    $orderInfo["order_pay_price"] = $payer_total;
    $shippingData["out_trade_no"] = $inBodyResourceArray["out_trade_no"];
    $shippingData["item_desc"] = $data_remarks;
    $shippingData["logistics_type"] = 4;
    $shippingData["openid"] = $userInfo["openid"];
    sleep(3);
    $db->startTrans();
    try {
        $uploadShippingInfo = uploadShippingInfo($shippingData);//微信发货通知
        if($uploadShippingInfo["errcode"] != 0){
            $content = "微信发货通知失败=>错误代码：".$uploadShippingInfo["errcode"].",错误原因：".$uploadShippingInfo["errmsg"]."单号：".$inBodyResourceArray["out_trade_no"].",时间：".date("Y-m-d H:i:s",time());
            Utils::writePayLog($content);
        }
        if($orderInfo["type"] == 1){//线下商家更新余额和明细
            offlineSettlement($db,$orderInfo);
        }
        if($orderInfo["type"] == 2){//线上商家更新余额和明细
            shopSettlement($db,$orderInfo);
        }
        if (!$db->save($upOrderSql)) Common::exception("订单更新失败");
        if (!$db->save($addOrderSql)) Common::exception("用户流水更新失败");
        $db->commit();
    } catch (\Exception $e) {
        $db->rollback();
        $content = "扫码付失败=>支付单号：".$inBodyResourceArray["out_trade_no"].",支付金额：".$payer_total.",原因：".$e->getMessage().",时间：".date("Y-m-d H:i:s",time());
        Utils::writePayLog($content);
        Result::error($e->getMessage());
    }
    $messagesData["type"] = $orderInfo["type"];
    $messagesData["sid"] = $orderInfo["sid"];
    $messagesData["msg_type"] = 1;
    $messagesData["msg"] = $data_remarks;
    $messagesData["trade_no"] = $orderInfo["pay_no"];
    pushCrmMessages($messagesData);
    Result::success();
}
